/*
 * @Date: 2023-08-14 19:23:04
 * @LastEditors: lyx
 * @LastEditTime: 2023-11-17 09:34:52
 * @FilePath: \sup-mimi-program-server\src\weapp\weapp.service.ts
 * @Description:
 *
 */
import { Injectable, Inject } from '@nestjs/common';
import { ReturnModelType } from '@typegoose/typegoose';
import axios from 'axios';
import { InjectModel } from 'nestjs-typegoose';
import { CreateWeappDto } from './dto/create-weapp.dto';
import {
  QueryAccessTokenDto,
  QueryOpenIdByWxDto,
} from './dto/query-access-token.dto';
import { UpdateWeappDto } from './dto/update-weapp.dto';
import { Weapp as WeappSchema } from './entities/weapp.entity';
import { ConfigService } from '@nestjs/config';
import { IGetOpenIdFromWx } from './dto/query-openid.dto';
import { log } from 'console';
import { SendMessageDto } from './dto/send-message';

@Injectable()
export class WeappService {
  constructor(
    @InjectModel(WeappSchema)
    private readonly weappModel: ReturnModelType<typeof WeappSchema>,
  ) {}
  @Inject(ConfigService)
  private configService: ConfigService;

  // TODO: 持久化 token
  async getAccessToken() {
    const queryAccessTokenDto: QueryAccessTokenDto = {
      grant_type: 'client_credential',
      appid: this.configService.get('we_app.appid'),
      secret: this.configService.get('we_app.secret'),
    };

    const res = await axios.get(`https://api.weixin.qq.com/cgi-bin/token`, {
      params: {
        ...queryAccessTokenDto,
      },
    });
    console.log('getAccessToken res.data', res.data);
    return res?.data ?? {};
  }

  /**
   * @description: 获取手机号
   * @param {*} access_token 接口调用凭证
   * @param {*} code 手机号获取凭证
   * @return {*}
   */
  async getPhoneNumber(code = '') {
    const getTokenRes = await this.getAccessToken();
    const { access_token } = getTokenRes;
    if (access_token) {
      console.log('getPhoneNumber code', code);
      console.log('getPhoneNumber access_token', access_token);
      const res = await axios.post(
        `https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=${access_token}`,
        {
          code,
        },
      );
      console.log('getPhoneNumber res.data', res.data);
      return res?.data ?? {};
    }
    return getTokenRes;
  }

  /**
   * @description: 获取 openId
   * @return {*}
   */
  async getPhoneNumberByCrypto(code = '') {
    const { status, content } = await this.getOpenIdByWx(code);
    if (status) {
      const { openid, session_key } = content;
      // todo
    } else {
      return;
    }
  }

  /**
   * @description: 获取 openId
   * @return {*}
   */
  async getOpenId(code = '') {
    const wxRes = await this.getOpenIdByWx(code);
    return wxRes;
    // 先从数据表中查询如果没有则去微信获取
    const dbRes = await this.getOpenIdFromDb();
    if (!dbRes.id) {
      const wxRes = await this.getOpenIdByWx(code);
      return wxRes;
    }
    return dbRes;
  }

  async findAll() {
    return await this.weappModel.find();
  }

  /**
   * @description: 获取 openId
   * @return {*}
   */
  async getOpenIdByWx(code = '', body: IGetOpenIdFromWx = {}) {
    const queryAccessTokenDto: QueryOpenIdByWxDto = {
      grant_type: 'authorization_code',
      appid: this.configService.get('we_app.appid'),
      secret: this.configService.get('we_app.secret'),
      js_code: code,
    };

    const res = await axios.get(
      `https://api.weixin.qq.com/sns/jscode2session`,
      {
        params: {
          ...queryAccessTokenDto,
        },
      },
    );
    if (res?.data?.openId) {
      if (body.phone) {
        // 需要保存入库
        const { openId } = res?.data ?? {};
        return await this.createWxInfo({
          openId,
          phoneNumber: body.phone,
        });
      }
    }
    return res?.data ?? {};
  }

  /**
   * @description: 根据手机号 从数据库 获取 openId
   * @return {*}
   */
  async getOpenIdFromDb(phoneNumber = '') {
    return await this.weappModel.findOne({ phoneNumber });
  }

  /**
   * @description: 创建 phone/openId 表
   * @param {CreateBannerDto} createDto
   * @return {*}
   */
  async createWxInfo(createDto: CreateWeappDto) {
    const { phoneNumber, openId } = createDto;
    // 先查询是否存在该记录
    const findRes = await this.weappModel.findOne({ phoneNumber, openId });
    if (findRes?._id) {
      // 存在
      return findRes;
    }
    // 是否需要删除 已有的 ？
    await this.weappModel.deleteMany({
      phoneNumber: phoneNumber,
    });
    const res = await this.weappModel.create(createDto);
    return res;
  }

  async updateWxInfo(id: string, updateWeappDto: UpdateWeappDto) {
    return await this.weappModel.findByIdAndUpdate(id, updateWeappDto);
  }

  async removeWxInfo(id: string) {
    return await this.weappModel.findByIdAndRemove(id);
  }

  /**
   * @description: 发送订阅消息
   * @return {*}
   */
  async sendMessage() {
    const tokenRes = await this.getAccessToken();
    console.log('tokenRes', tokenRes);
    if (!tokenRes?.access_token) {
      return tokenRes;
    }
    const sendMessageDto: SendMessageDto = {
      template_id: this.configService.get('we_app.template.id'),
      touser: '0d1jQFFa1lw4oG0lLRHa1rTVga0jQFFE',
      page: 'pages/job/job', // 跳转到 任务页面
      data: {
        thing2: {
          value: '流程测试名称1',
        },
        name7: {
          value: 'name111',
        },
        date3: {
          value: '2023-08-14',
        },
        thing5: {
          value: '本级审核',
        },
      },
      miniprogram_state: 'developer',
      lang: 'zh_CN',
    };
    const dto = {
      template_id: 'dglxA6jLzBFwu9YIsgTmSH8ZqxtZJpkxqzoQ8zuBNmg',
      touser: '0d1jQFFa1lw4oG0lLRHa1rTVga0jQFFE',
      page: 'pages/job/job',
      data: {
        thing2: {
          value: '流程测试名称1',
        },
        name7: {
          value: 'name111',
        },
        date3: {
          value: '2023-08-14',
        },
        thing5: {
          value: '本级审核',
        },
      },
      miniprogram_state: 'developer',
      lang: 'zh_CN',
    };
    const token =
      '74_TyYkAttusrVZYmI6J6yheUCpHN2q8zw-Bmh4zBVf7l2yEDsw-RsVa96JAznUKbdCfYwX9ePUpYaugwfnxoeoCRlkQ_6zb7XKyG1phPkYooI40v8lnSQsR4gsAbMGELdAIAPNU';
    const str = JSON.stringify(sendMessageDto);
    console.log('sendMessage dto', sendMessageDto);

    const res = await axios.post(
      `https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${tokenRes.access_token}`,
      // `https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=${token}`,
      sendMessageDto,
      { headers: { 'Content-Type': 'application/json' } },
    );
    console.log('sendMessage res', res?.data);
    return res?.data ?? {};
  }
}
